#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <math.h>

#define TAM_PALAVRA 70
#define TAM_FRASE 100
#define TAM_BLOCO 100

int busca_palindromo(char *s);
int verificador(char *s);
void verifica_bloco(char *bloco, char **palavra, int *num);//parser para verificar palavra por palvara
void verifica_bloco2(char *bloco, char **frase, int *num); //parser para verificar frase por frase

int main (int argc, char *argv[]){
        int i = 0, j = 0, num1 = 0, num2 = 0;
        char bloco[TAM_BLOCO], *palavra[TAM_PALAVRA], *frase[TAM_FRASE];
        int contFr = 0, contPa = 0, valor1 = 0, valor2 = 0;

        FILE *arq_pequeno;

        arq_pequeno = fopen("shakespe.txt","r");

        if (arq_pequeno!=NULL){//exception
                while(!feof(arq_pequeno)){//Lê o arquivo, separa-o em threads(2), e processa-o


                        fgets(bloco,TAM_BLOCO,arq_pequeno);
			//Comando que separa o processo em 2 threads, com valores privados e valores compatilhados
                       #pragma omp parallel num_threads(2) private(i,valor1,valor2) reduction(+:contPa,contFr) shared(bloco,palavra,frase)
                            verifica_bloco2(bloco,frase,&num1);

                            for(i = 0;i < num1;i++)
                            {
				//verifica se as frases sao palindromos
                                 valor1 = verificador(frase[i]);
                                 if(valor1 != 0)
				//variavel critica em que cada thread acessa um de cada vez	
                                  #pragma omp critical
                                        contFr++;

                                      verifica_bloco(frase[i],palavra,&num2);

                                 for(j = 0;j < num2;j++)
                                 {	//verifica se as palavras sao palindromos
                                        valor2 = verificador(palavra[j]);
                                        if(valor2 != 0)
                                        #pragma omp critical
                                        contPa++;
                                 }
                            }

                }
        printf("Palindromos frases: %d\nPalindromos palavras: %d\n",contFr,contPa);
        }
   fclose(arq_pequeno);
   //----------------------------------------------
   //----------------------------------------------
   return 0;
}
//--------------------------------------------------
//--------------------------------------------------
//--------------------------------------------------
void verifica_bloco2(char *bloco, char **frase, int *num){ //parser para verificar frase por frase
        int m = 0;

        char *frase_aux = strtok(bloco, ".?!");

        while(frase_aux != NULL){
                frase[m] = frase_aux;
                frase_aux = strtok(NULL, ".?!");
                m++;
        }
       *num = m;
}

void verifica_bloco(char *frase, char **palavra, int *num){ //parser para verificar palavra por palavra
        int m = 0;

        char *palavra_aux = strtok(frase, " ,./?'\";:|^-!$#@`~*&%)(+=_}{][\n\r\t\\");

        while(palavra_aux != NULL){
                palavra[m] = palavra_aux;
                palavra_aux = strtok(NULL, " ,./?'\";:|^-!$#@`~*&%)(+=_}{][\n\r\t\\");
                m++;
        }
        *num = m;
}

/**converte para minusculo se necessário, verifica já se é palindromo**/
/**retorna o valor total em ascii**/
int verificador(char *s){
        int i = 0, j = 0, test = 0;
        char bloco[100];

        for(i=0; i < strlen(s); i++){
                if (isupper(s[i])){ /**maiusculo->minusculo**/
                        s[i] += 32;
                        bloco[j++] = s[i];
                }
                else if(isdigit(s[i]) || islower(s[i])){ /**verifica se já numeros no meio ou se já é minuscula **/
                        bloco[j++] = s[i];
                }
                /*else if(s[i] == ' ' || s[i] == '\n'/ || s[i] == '-'/ || s[i] == ':')
                        j++; //coloca final de string*/
                else
                        bloco[j] = '\0'; //coloca final de string
        }

        test = busca_palindromo(bloco);

        return test;
}

/**verifica se a palavra é palindrmo e já converte para ascii**/
int busca_palindromo(char *s){
        int i, l = 0, count = 0;
        l = strlen(s);

        if (l == 0)
                return 0;

        for(i = 0; i < l/2; i++){ /**para palindromo par**/
                if ( s[i] != s[l-i-1] ) /** se já for diferente o inicio e o fim retorna 0 **/
                        return 0;
                /**senão vai somando o inicio e o fim da palavra e convertendo para ascii**/
                count += s[i];
                count += s[l-i-1];
        }
        if(l%2 == 1)/**para palindromo impar soma o termo do meio**/
                return (count + s[1+l/2]);

        else
                return count;
}

